use std::{
    env, fs,
    path::Path,
    process::{Command, exit},
};
use chrono::Utc;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 环境预检
    check_build_environment()?;

    // 2. 生成版本信息
    generate_version_file()?;

    // 3. 处理策略文件
    setup_polkit_policies()?;

    // 4. 构建本地组件
    build_native_libs()?;

    // 5. 生成SLINT资源
    compile_slint_ui()?;

    Ok(())
}

/// 检查编译环境依赖
fn check_build_environment() -> Result<(), String> {
    let required_tools = [
        ("bsdiff", "bsdiff工具（需v4.3+）"),
        ("qemu-aarch64-static", "QEMU用户态模拟"),
        ("patchelf", "ELF二进制修改"),
    ];

    for (bin, desc) in &required_tools {
        if Command::new("which")
            .arg(bin)
            .status()
            .map(|s| !s.success())
            .unwrap_or(true)
        {
            return Err(format!("缺失必要依赖: {} ({})", bin, desc));
        }
    }

    // 检查Rust版本
    let rust_version = env::var("RUSTC").unwrap_or_else(|_| "rustc".into());
    let output = Command::new(rust_version)
        .arg("--version")
        .output()
        .expect("无法获取Rust版本");
    let version_str = String::from_utf8_lossy(&output.stdout);
    let version = version_str
        .split_whitespace()
        .nth(1)
        .and_then(|v| v.split('.').next())
        .and_then(|v| v.parse::<u32>().ok())
        .unwrap_or(0);

    if version < 2021 {
        return Err("需要Rust 2021 Edition或更高版本".into());
    }

    Ok(())
}

/// 生成版本元数据文件
fn generate_version_file() -> Result<(), Box<dyn std::error::Error>> {
    let out_dir = env::var("OUT_DIR")?;
    let dest_path = Path::new(&out_dir).join("version.rs");
    
    let git_hash = Command::new("git")
        .args(&["rev-parse", "--short", "HEAD"])
        .output()
        .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
        .unwrap_or_else(|_| "unknown".into());

    let build_time = Utc::now().format("%Y-%m-%d %H:%M:%S").to_string();

    fs::write(
        &dest_path,
        format!(
            r#"
            pub const GIT_COMMIT: &str = "{}";
            pub const BUILD_TIME: &str = "{}";
            pub const TARGET_ARCH: &str = "{}";
            "#,
            git_hash,
            build_time,
            env::var("TARGET").unwrap_or_default()
        ),
    )?;

    // 告诉Cargo需要重新生成的条件
    println!("cargo:rerun-if-changed=.git/HEAD");
    println!("cargo:rerun-if-changed=.git/index");
    Ok(())
}

/// 安装Polkit策略文件
fn setup_polkit_policies() -> Result<(), Box<dyn std::error::Error>> {
    let policy_src = "data/org.deepin.linglong.install.policy";
    let policy_dest = "/usr/share/polkit-1/actions";
    
    if !Path::new(policy_dest).exists() {
        fs::create_dir_all(policy_dest)?;
    }

    // 仅当以root身份编译时尝试安装
    if users::get_effective_uid() == 0 {
        fs::copy(policy_src, Path::new(policy_dest).join("org.deepin.linglong.install.policy"))?;
    } else {
        println!(
            "cargo:warning=请手动安装策略文件: sudo install {} {}",
            policy_src, policy_dest
        );
    }

    Ok(())
}

/// 编译本地C组件（示例）
fn build_native_libs() -> Result<(), Box<dyn std::error::Error>> {
    let target = env::var("TARGET")?;
    let is_cross = target != env::var("HOST")?;

    if is_cross {
        // 交叉编译时设置工具链
        let toolchain = match target.as_str() {
            "aarch64-unknown-linux-gnu" => "aarch64-linux-gnu",
            "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32",
            _ => "",
        };

        if !toolchain.is_empty() {
            env::set_var("CC", format!("{}-gcc", toolchain));
            env::set_var("AR", format!("{}-ar", toolchain));
        }
    }

    // 构建示例C库
    cc::Build::new()
        .file("src/native/helper.c")
        .compile("linglong_helper");

    Ok(())
}

/// 编译SLINT UI文件
fn compile_slint_ui() -> Result<(), Box<dyn std::error::Error>> {
    let ui_files = [
        "src/gui/resources/main.slint",
        "src/gui/resources/preferences.slint",
    ];

    for file in &ui_files {
        slint_build::compile(file)?;
        println!("cargo:rerun-if-changed={}", file);
    }

    Ok(())
}

/// 构建失败时的友好提示
fn show_build_help(error: &str) {
    eprintln!(
        r#"
        !!! 构建失败 !!!
        原因: {}

        常见解决方法:
        1. 安装缺失工具:
           sudo apt install bsdiff qemu-user-static patchelf
        2. 配置交叉编译环境:
           sudo apt install gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
        3. 更新Rust工具链:
           rustup update stable && rustup default stable
        "#,
        error
    );
    exit(1);
}

// 主函数错误处理包装
fn main() {
    if let Err(e) = main() {
        show_build_help(&e.to_string());
    }
}